#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "../umlcore/PartialElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class TemplateParameter;

/// <summary>
/// ParameterableElement
/// A ParameterableElement is an Element that can be exposed as a formal
/// TemplateParameter for a template, or specified as an actual parameter in a
/// binding of a template.
/// </summary>
class UMLMODEL_EXPORT ParameterableElement : public PartialElement {

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// isCompatibleWith
    /// The query isCompatibleWith() determines if this ParameterableElement is
    /// compatible with the specified ParameterableElement. By default, this
    /// ParameterableElement is compatible with another ParameterableElement p if the
    /// kind of this ParameterableElement is the same as or a subtype of the kind of p.
    /// Subclasses of ParameterableElement should override this operation to specify
    /// different compatibility constraints.
    /// </summary>
    virtual bool isCompatibleWith(shared_ptr<ParameterableElement> p) const;

    /// <summary>
    /// isTemplateParameter
    /// The query isTemplateParameter() determines if this ParameterableElement is
    /// exposed as a formal TemplateParameter.
    /// </summary>
    virtual bool isTemplateParameter() const;

public: // Properties
    /// <summary>
    /// owningTemplateParameter getter
    /// The formal TemplateParameter that owns this ParameterableElement.
    /// </summary>
    shared_ptr<TemplateParameter> owningTemplateParameter() const;

    /// <summary>
    /// owningTemplateParameter setter
    /// The formal TemplateParameter that owns this ParameterableElement.
    /// </summary>
    void setOwningTemplateParameter(shared_ptr<TemplateParameter> value);

    /// <summary>
    /// templateParameter getter
    /// The TemplateParameter that exposes this ParameterableElement as a formal
    /// parameter.
    /// </summary>
    shared_ptr<TemplateParameter> templateParameter() const;

    /// <summary>
    /// templateParameter setter
    /// The TemplateParameter that exposes this ParameterableElement as a formal
    /// parameter.
    /// </summary>
    void setTemplateParameter(shared_ptr<TemplateParameter> value);

private: // Fields
    /// <summary>
    /// owningTemplateParameter
    /// The formal TemplateParameter that owns this ParameterableElement.
    /// </summary>
    shared_ptr<TemplateParameter> owningTemplateParameter_;

    /// <summary>
    /// templateParameter
    /// The TemplateParameter that exposes this ParameterableElement as a formal
    /// parameter.
    /// </summary>
    shared_ptr<TemplateParameter> templateParameter_;

};

} // namespace uml
